import { nmAppErrorLog, nmAppLog } from '@app-nextmesh/common/utils';
import { documentV2 } from '@app-nextmesh/domain';
import { useProjectStore } from '@app-nextmesh/store/project';
import { useTasksStore } from '@app-nextmesh/store/tasks';
import { GspEventType, IGspEvent, ITask } from '@app-nextmesh/types';
import { events } from '@app-nextmesh/utils';
import { Avatar, Flex, FloatButton, List, notification, Progress } from 'antd';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import { cloneDeep, isArray } from 'lodash';
import VirtualList from 'rc-virtual-list';
import React, { useEffect, useRef, useState } from 'react';
import { ReactComponent as ErrorIcon } from './icon/error-icon.svg';
import { ReactComponent as SuccessIcon } from './icon/success-icon.svg';
import { ReactComponent as TaskList } from './icon/task-list.svg';
import './styles.scss';
dayjs.extend(utc);
export default function Task() {
  const { projectInfo, setProjectInfo } = useProjectStore();
  const [percent, setPercent] = useState<number>(0);
  const [api, contextHolder] = notification.useNotification();
  const [openFloat] = useState<boolean>(false);
  const initDatetime = useRef<dayjs.Dayjs>(null);
  // 根据started时间过滤后的任务列表State
  const [filteredTaskList, setFilteredTaskList] = useState<ITask[]>([]);
  // 最新成功的任务id
  const lastSuccessTask = useRef(null);
  const { tasks, setTasks } = useTasksStore();

  useEffect(() => {
    if (!isArray(tasks)) {
      return;
    }
    if (tasks.length === 0) {
      initDatetime.current = dayjs().subtract(10, 'minute'); // 10分钟前，防止任务执行了，还没有获取到任务列表
      return;
    }
    // 如果是第一次，初始化过滤时间
    if (initDatetime.current == null) {
      // 循环找到第一个成功的任务，以它的时间作为过滤时间；没找到就用当前时间
      const firstSuccessTask = tasks?.find(
        (task) => task.status === 'FINISHED',
      );
      initDatetime.current = dayjs
        .utc(firstSuccessTask?.started || dayjs())
        .local();
    }
    // 过滤任务
    const filteredTasks = tasks.filter((task) => {
      const started = dayjs.utc(task.started).local();
      return initDatetime.current.diff(started) < 0;
    });
    // 获取最新一条执行中的任务进度
    for (const task of filteredTasks) {
      if (task.status === 'STARTED') {
        setPercent(task.progress * 100);
        break;
      }
    }
    setFilteredTaskList(filteredTasks);
    nmAppLog('Task', 'filteredTaskList', filteredTasks);
    // 第一个是最新的
    const lastTask = filteredTasks[0];
    if (lastTask?.status === 'FINISHED') {
      lastSuccessTask.current = lastTask;
    }
  }, [tasks]);
  useEffect(() => {
    // 统一在这里监听任务更新，然后使用 useTasksStore 来更新任务列表，在使用了 useTasksStore 的地方会自动更新
    events.on(GspEventType.taskupdated, handleTaskUpdated);
    return () => {
      events.off(GspEventType.taskupdated, handleTaskUpdated);
    };
  }, [projectInfo]);
  const updateTasks = (task: ITask) => {
    if (!task) {
      return [];
    }
    const index = tasks.findIndex(({ uuid }) => uuid === task.uuid);
    if (index > -1) {
      tasks[index] = task;
    } else {
      // 插入数组头部
      tasks.unshift(task);
    }
    const newTasks = [...tasks];
    setTasks(newTasks);
    return newTasks;
  };
  const handleTaskUpdated = async (event: IGspEvent) => {
    const task = event.data as ITask;
    nmAppLog('Task handleTaskUpdated', { task, filteredTaskList });
    if (!task) {
      return;
    }
    let found = false;
    filteredTaskList.forEach((item, index) => {
      if (item.uuid === task.uuid) {
        found = true;
        filteredTaskList[index] = task;
      }
    });
    if (!found) {
      filteredTaskList.push(task);
    }
    const newTasks = updateTasks(task);
    setFilteredTaskList(cloneDeep(filteredTaskList));
    nmAppLog('Task handleTaskUpdated filteredTaskList', filteredTaskList);
    if (task.status === 'FINISHED') {
      if (task.moduleId === 'mesh') {
        // 网格的任务成功了
        // GSP使用的是Worker，无法发送GspEvent，所以我们这里模拟
        const event: IGspEvent = {
          uuid: task.moduleId,
          event: GspEventType.meshChanged,
        };
        events.emit(event.event, event);
        return;
      }
      try {
        const results = await documentV2.listResults();
        const newTasks2 = [...newTasks]
          // 因为任务列表是倒序的，所以反转任务列表
          ?.reverse()
          // 过滤掉mesh任务
          .filter((item) => item.type !== 'mesh');
        setProjectInfo({
          ...projectInfo,
          tasks: newTasks2,
          results,
        });
      } catch (error) {
        nmAppErrorLog('Task handleTaskUpdated listResults', error);
      }
    }
  };
  // 滚动设置高度
  const ContainerHeight = 400;
  // 下拉滚动检查方法
  const onScroll = (e: React.UIEvent<HTMLElement, UIEvent>) => {
    if (
      Math.abs(
        e.currentTarget.scrollHeight -
          e.currentTarget.scrollTop -
          ContainerHeight,
      ) <= 1
    ) {
      console.log('todo');
    }
  };

  // 任务状态图标展示
  const CircularProgressWithLabel = ({ taskData }: { taskData: ITask }) => {
    switch (taskData?.status) {
      case 'FINISHED':
        return <Avatar icon={<SuccessIcon />} />;
      case 'FAILED':
        return <Avatar icon={<ErrorIcon />} />;
      default:
        return (
          <Progress
            size={40}
            percent={taskData?.progress ? taskData.progress * 100 : 0}
            type='circle'
            trailColor='#e6f4ff'
            strokeWidth={10}
          />
        );
    }
  };

  // 关闭任务状态方法
  const closeNotification = () => {
    console.log('openNotification:');
  };

  // 打开任务状态方法
  const openNotification = (e) => {
    nmAppLog('openNotification:', e, filteredTaskList, percent);
    const jobAll = filteredTaskList;
    api.open({
      key: 'updatable',
      onClose: closeNotification,
      message: <span className='taskTitle'>任务状态</span>,
      placement: 'bottomRight',
      description: (
        <List>
          <VirtualList
            data={jobAll}
            height={ContainerHeight}
            itemHeight={47}
            itemKey={(item) => item.uuid}
            onScroll={onScroll}>
            {(item: ITask) => (
              <List.Item key={item.uuid}>
                <List.Item.Meta
                  avatar={<CircularProgressWithLabel taskData={item} />}
                  title={<a>{item.type}</a>}
                  description={item.status}
                />
                {/*<Button type='link'>终止</Button>*/}
              </List.Item>
            )}
          </VirtualList>
        </List>
      ),
      duration: 0,
    });
  };

  // 封装悬浮按钮进度条方法
  const ProgressBody = () => {
    return (
      <div className='proressBody'>
        <Flex
          align='center'
          gap='small'>
          <Progress
            size={40}
            percent={percent}
            type='circle'
            trailColor='#e6f4ff'
            strokeWidth={10}
            format={() => (
              <span>
                <TaskList className='taskListIcon' />
              </span>
            )}
          />
        </Flex>
      </div>
    );
  };
  return (
    <>
      {contextHolder}
      <FloatButton.Group
        open={openFloat}
        trigger='click'
        style={{ insetInlineEnd: 20 }}
        onClick={() => openNotification(percent)}
        icon={<ProgressBody />}>
        <></>
      </FloatButton.Group>
    </>
  );
}
